/*
"The contents of this file are subject to the Mozilla Public License
Version 1.1 (the "License"); you may not use this file except in
compliance with the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/

Software distributed under the License is distributed on an "AS IS"
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
License for the specific language governing rights and limitations
under the License.

The Original Code is ReportSheet.

The Initial Developer of the Original Code is Amarnath Chatterjee.
Portions created by Amarnath Chatterjee are Copyright (C). All Rights Reserved.

Contributor(s): Amarnath Chatterjee.
*/

package Reporting
{
	import Reporting.Utils.CellEditPanel;
	
	import mx.controls.TextInput;
	import mx.controls.dataGridClasses.DataGridListData;
	import mx.core.UIComponent;
	import mx.events.FlexEvent;
	import flash.events.MouseEvent;
	import flash.events.Event;
	import flash.geom.Point;
	import mx.managers.PopUpManager;
	
	//This class is the cell renderer for reportsheet. Handles two things.
	//1. Data styling.
	//2. Mouse based navigation.
	public class CellRenderer extends TextInput
	{
		public static const BGCOLOR : String = "backgroundColor";
		public static const FONTCOLOR : String = "color";
		public static const FONTSTYLE : String = "fontStyle";
		public static const FONTWEIGHT : String = "fontWeight";
		public static const FONTNORMAL : String = "normal";
		public static const FONTITALIC : String = "italic";
		public static const FONTBOLD : String = "bold";
		
		private static var DEFAULT_VALUES : Array = new Array();
		private static var INIT_DEFAULTS : Boolean = InitDefaults();
		
		private static function InitDefaults() : Boolean
		{
			DEFAULT_VALUES[BGCOLOR] = "0xffffff";
			DEFAULT_VALUES[FONTCOLOR] = "0x0B333C";
			DEFAULT_VALUES[FONTSTYLE] = "normal";
			DEFAULT_VALUES[FONTWEIGHT] = "normal";
			return true;
		}
		
		
		public function CellRenderer()
		{
			super();
			
			setStyle("borderStyle", "none");
			setStyle("borderSides","left top right bottom");
			setStyle("borderThickness", 2);
			setStyle("borderColor",0x00ccff);
			addEventListener(MouseEvent.MOUSE_WHEEL, MouseWheelHandler);
		}
		

//------------------------------------------------------------------------------------------------------------------
//										Event Handling Functions.
//------------------------------------------------------------------------------------------------------------------
		//If mouse wheel is rolled over a cell, it zooms out a cell editor panel for better cell editing.
		//The panel is created as a popup and is capable of even styling the cell. When the panel is brought up,
		//listdata and super.data is read to find out all cell information. Various styling components are 
		//configured in controls of cellEdit panel.
		public function MouseWheelHandler(fe : Event) : void
		{
			var col : int = DataGridListData(listData).columnIndex;
			var row : int = DataGridListData(listData).rowIndex;
			var dt : String;
			
			//If it is locked don't do anything.
			if(CheckLock())
				return;
				
			//If there is mathematical expression then show it, else show the data.
			if(super.data[DataGridListData(listData).dataField].@[ReportSheet.MATH_EXPRN_ATTR] == undefined)
			{
				dt = super.data[DataGridListData(listData).dataField];
			}
			else
			{
				dt = ReportSheet.EQU_IDENTIFIER + super.data[DataGridListData(listData).dataField].@mathExprn;
			}
			
			if(!CellEditPanel.PANEL_ACTIVE)
			{
				var CellEditor : CellEditPanel = CellEditPanel(PopUpManager.createPopUp(this, CellEditPanel));
				CellEditor.title = row+","+col;
				CellEditor.CellVal.text = dt;
				
				if(super.data[DataGridListData(listData).dataField].@[BGCOLOR] != undefined)
				{
					CellEditor.CellVal.setStyle(BGCOLOR, super.data[DataGridListData(listData).dataField].@[BGCOLOR]);	
				}
				if(super.data[DataGridListData(listData).dataField].@[FONTCOLOR] != undefined)
				{
					CellEditor.CellVal.setStyle(FONTCOLOR, super.data[DataGridListData(listData).dataField].@[FONTCOLOR]);	
				}
				if(super.data[DataGridListData(listData).dataField].@[FONTSTYLE] != undefined)
				{
					CellEditor.CellVal.setStyle(FONTSTYLE, super.data[DataGridListData(listData).dataField].@[FONTSTYLE]);	
				}
				if(super.data[DataGridListData(listData).dataField].@[FONTWEIGHT] != undefined)
				{
					CellEditor.CellVal.setStyle(FONTWEIGHT, super.data[DataGridListData(listData).dataField].@[FONTWEIGHT]);	
				}
				
				//Callback to initimate updates in the cell
				CellEditor.CellUpdt_CallBack = CellUpdated;
				CellEditor.LazyInit();
				WrkArndCenterPopup(CellEditor, this);
			} 	
		}
		
		//This function is a work around as it is been reported from many places that PopupManager.CenterPopup()
		//is not working properly in flex 3.4+ versions. Have seen this workaround in some blog
		public static function WrkArndCenterPopup(popup: UIComponent, centerOn: UIComponent): void
 		{
			var pt:Point = new Point(0, 0);
			pt = centerOn.localToGlobal(pt); // Convert local 0,0 into global coordinate
			pt = popup.globalToLocal(pt); // Convert the result into local coordinate of myPop
			popup.move(Math.round((centerOn.width - popup.width) / 2) + pt.x,
			Math.round((centerOn.height - popup.height) / 2) + pt.y);
		}
		
		//This function finds out whether this cell is locked or not.
		private function CheckLock() : Boolean
		{
			if(super.data[DataGridListData(listData).dataField].@[ReportSheet.LOCK_EXPRN_ATTR] == undefined)
			{
				return false;
			}
			else
			{
				return Boolean(super.data[DataGridListData(listData).dataField].@[ReportSheet.LOCK_EXPRN_ATTR]);
			}
		}
		//Callback function, used to tell what all is updated. This function finally dispatches a bubbling event
		//The event object used is cell info. All data and style information is stuffed in CellInfo object and is bubbled
		//out. Later of Reportsheet catches this event.
		public function CellUpdated(IsDataUpdated:Boolean, 
									newVal : String, 
									IsStyleUpdated:Boolean, 
									IsBold : Boolean, 
									IsItalics : Boolean,
									BGCol : String, 
									FntColor : String ) : void
		{
			var cellupdtev : CellInfo = new CellInfo();
			cellupdtev.row = DataGridListData(listData).rowIndex;
			cellupdtev.col = DataGridListData(listData).columnIndex;
			cellupdtev.data = newVal;
			cellupdtev.IsCellDataUpdate = IsDataUpdated;
			cellupdtev.IsStyleUpdated = IsStyleUpdated;
			cellupdtev.backgroundColor = BGCol;
			cellupdtev.fontColor = FntColor;
			
			if(IsBold)
				cellupdtev.fontBold = FONTBOLD;
			else
				cellupdtev.fontBold = FONTNORMAL; 
				
			if(IsItalics)
				cellupdtev.fontStyle = FONTITALIC;
			else
				cellupdtev.fontStyle = FONTNORMAL; 
			
			dispatchEvent(cellupdtev);				
		}
		
//------------------------------------------------------------------------------------------------------------------
//											Rendering Functions.
//------------------------------------------------------------------------------------------------------------------

		//If a component implements the IDropInListItemRenderer(like TextInput) interface, you can use its listData property 
		//to obtain information about the data passed to the component when you use the component in an item renderer or item editor.
		//To set any style for a particular cell. Just pass on the style name and value as attributes to xml-node for that cell.
		override public function set data(value:Object):void
		{
			super.data = value;
			if(value != null)
			{
				//Setting data to my text field.
				text = value[DataGridListData(listData).dataField];
				
				//These are not usefull as such over here. But just keeping them for reference.
				//var df : String = DataGridListData(listData).dataField;
				//var col : int = DataGridListData(listData).columnIndex;
				//var row : int = DataGridListData(listData).rowIndex;
				
				var rowXML : XML = XML(value);
				SetAllStyles(rowXML);
				
				dispatchEvent(new FlexEvent(FlexEvent.DATA_CHANGE));
			}
			
		}
		
		//This function sets all the styles for the current cell. This function expects the row xml for the current row.
		//Two things to keep in mind here.
		//1.Whenever you set a style remember that you need to give exactly expected format of data type.
		//	such that it doesn't defers it to a later stage.
		//2.Always reset styles to default values. CellRenderes are going to be reused.
		private function SetAllStyles(rowXML : XML) : void
		{
			var df : String = DataGridListData(listData).dataField;
			if(rowXML.child(df)[0].@[BGCOLOR] == undefined)
			{
				setStyle(BGCOLOR, parseInt(DEFAULT_VALUES[BGCOLOR]));
			}
			else
			{
				setStyle(BGCOLOR, parseInt(rowXML.child(df)[0].@[BGCOLOR]));	
			}
			
			if(rowXML.child(df)[0].@[FONTCOLOR] == undefined)
			{
				setStyle(FONTCOLOR, parseInt(DEFAULT_VALUES[FONTCOLOR]));
			}
			else
			{
				setStyle(FONTCOLOR, parseInt(rowXML.child(df)[0].@[FONTCOLOR]));	
			}

			if(rowXML.child(df)[0].@[FONTSTYLE] == undefined)
			{
				setStyle(FONTSTYLE, DEFAULT_VALUES[FONTSTYLE].toString());
			}
			else
			{
				setStyle(FONTSTYLE, rowXML.child(df)[0].@[FONTSTYLE].toString());	
			}
			
			if(rowXML.child(df)[0].@[FONTWEIGHT] == undefined)
			{
				setStyle(FONTWEIGHT, DEFAULT_VALUES[FONTWEIGHT].toString());
			}
			else
			{
				setStyle(FONTWEIGHT, rowXML.child(df)[0].@[FONTWEIGHT].toString());	
			}
		}
	}
}